package com.smart.community.user.service.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.service.BaseServiceCaller;
import com.smart.community.feign.device.IDeviceStatisticsFeign;
import com.smart.community.feign.parking.IParkingStatisticsFeign;
import com.smart.community.feign.property.IPropertyStatisticsFeign;
import com.smart.community.feign.property.service.DataScopeFeign;
import com.smart.community.feign.region.service.IRegionStatisticsFeign;
import com.smart.community.user.service.CacheService;
import com.smart.community.user.service.DashboardService;
import com.smart.community.user.service.UserService;
import com.smart.community.user.util.CacheUtil;
import com.smart.community.user.vo.DashboardChartVO;
import com.smart.community.user.vo.DashboardNoticeVO;
import com.smart.community.user.vo.DashboardStatsVO;
import com.smart.community.user.vo.DashboardVO;

import lombok.extern.slf4j.Slf4j;

/**
 * 仪表盘服务实现类
 * 
 * 继承BaseServiceCaller，使用统一的服务调用模板
 * 提供完善的异常处理和降级策略
 * 
 * @author Wu.Liang
 * @version 2.3.0
 * @since 2025-01-30
 * @updated 2025-08-28 - 继承BaseServiceCaller，使用safeCall方法
 * @updated 2025-08-28 - 修复缓存反序列化ClassCastException问题
 * @updated 2025-01-30 - 按照Java后端SpringBoot代码开发规范优化
 * @updated 2025-01-30 - 修复数据权限逻辑，物业公司用户使用DataScopeInfo中的communityIds
 */
@Slf4j
@Service
public class DashboardServiceImpl extends BaseServiceCaller implements DashboardService {
	
	@Autowired
	private DataScopeFeign dataScopeFeign;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private IRegionStatisticsFeign regionStatisticsFeign;
	
	@Autowired
	private IParkingStatisticsFeign parkingStatisticsFeign;
	
	@Autowired
	private IDeviceStatisticsFeign deviceStatisticsFeign;
	
	@Autowired
	private IPropertyStatisticsFeign propertyStatisticsFeign;
	
	@Autowired
	private CacheService cacheService;

    @Override
    public DashboardVO getDashboardData(Long currentUserId) throws Exception {
        // 验证用户ID
        if (currentUserId == null) {
            log.warn("用户ID为空，无法获取仪表盘数据");
            throw new BusinessException("用户未登录或登录状态异常，请重新登录");
        }
        
        log.info("获取仪表盘数据，当前用户ID：{}", currentUserId);
        
        // 缓存键：dashboard:data:用户ID
        String cacheKey = "dashboard:data:" + currentUserId;
        
        try {
            // 1. 尝试从缓存获取
            Object cachedObject = cacheService.get(cacheKey, Object.class);
            if (cachedObject != null) {
                // 使用缓存工具类安全地处理缓存反序列化问题
                DashboardVO cachedData = CacheUtil.safeConvert(cachedObject, DashboardVO.class);
                if (cachedData != null) {
                    log.debug("从缓存获取仪表盘数据成功，用户ID：{}", currentUserId);
                    return cachedData;
                } else {
                    log.warn("缓存数据格式异常，重新构建数据，用户ID：{}", currentUserId);
                    // 清除异常的缓存数据
                    cacheService.delete(cacheKey);
                }
            }
            
            // 2. 缓存未命中，构建数据
            DashboardVO dashboardData = buildDashboardData(currentUserId);
            
            // 3. 缓存数据（5分钟过期）
            cacheService.set(cacheKey, dashboardData, 300);
            log.debug("仪表盘数据已缓存，用户ID：{}", currentUserId);
            
            return dashboardData;
        } catch (Exception e) {
            log.warn("缓存操作失败，直接构建数据，用户ID：{}", currentUserId, e);
            return buildDashboardData(currentUserId);
        }
    }
    
    /**
     * 构建仪表盘数据
     * 
     * @param currentUserId 当前用户ID
     * @return 仪表盘数据
     * @throws Exception 统一异常
     */
    private DashboardVO buildDashboardData(Long currentUserId) throws Exception {
        // 获取用户数据权限信息
        DataScopeInfo dataScopeInfo = dataScopeFeign.getUserDataScope(currentUserId);
        log.info("用户数据权限信息：{}", dataScopeInfo);
        
        // 构建统计数据
        DashboardStatsVO stats = buildStatsData(dataScopeInfo);
        
        // 构建图表数据
        DashboardChartVO chart = buildChartData(dataScopeInfo);
        
        // 构建公告数据
        List<DashboardNoticeVO> notices = buildNoticeData();
        
        return DashboardVO.builder()
                .stats(stats)
                .chart(chart)
                .notices(notices)
                .build();
    }

    /**
     * 构建统计数据
     * 
     * @param dataScopeInfo 用户数据权限信息
     * @return 统计数据
     */
    private DashboardStatsVO buildStatsData(DataScopeInfo dataScopeInfo) {
        DashboardStatsVO stats = DashboardStatsVO.builder()
                .totalUsers(0L)
                .totalCommunities(0L)
                .totalParkingSpaces(0L)
                .onlineDevicesPercent(0.0)
                .totalBuildings(0L)
                .totalUnits(0L)
                .totalHouseholds(0L)
                .totalOwners(0L)
                .build();

        try {
            // 根据用户权限范围获取统计数据
            if (dataScopeInfo.isSuperAdmin()) {
                // 超级管理员：显示所有数据
                stats.setTotalUsers(getTotalUsersForSuperAdmin());
                stats.setTotalCommunities(getTotalCommunitiesForSuperAdmin());
                stats.setTotalParkingSpaces(getTotalParkingSpacesForSuperAdmin());
                stats.setOnlineDevicesPercent(getDeviceOnlineRateForSuperAdmin());
                stats.setTotalBuildings(getTotalBuildingsForSuperAdmin());
                stats.setTotalUnits(getTotalUnitsForSuperAdmin());
                stats.setTotalHouseholds(getTotalHouseholdsForSuperAdmin());
                stats.setTotalOwners(getTotalOwnersForSuperAdmin());
            } else if (dataScopeInfo.isPropertyCompanyUser()) {
                // 物业公司用户：显示本公司数据
                List<Long> propertyCompanyIds = dataScopeInfo.getPropertyCompanyIds();
                List<Long> communityIds = dataScopeInfo.getCommunityIds();
                
                log.info("物业公司用户数据权限 - 物业公司IDs: {}, 社区IDs: {}", propertyCompanyIds, communityIds);
                
                stats.setTotalUsers(getTotalUsersByPropertyCompanies(propertyCompanyIds));
                stats.setTotalCommunities(getTotalCommunitiesByIds(communityIds));
                stats.setTotalParkingSpaces(getTotalParkingSpacesByCommunities(communityIds));
                stats.setOnlineDevicesPercent(getDeviceOnlineRateByCommunities(communityIds));
                stats.setTotalBuildings(getTotalBuildingsByCommunities(communityIds));
                stats.setTotalUnits(getTotalUnitsByCommunities(communityIds));
                stats.setTotalHouseholds(getTotalHouseholdsByCommunities(communityIds));
                stats.setTotalOwners(getTotalOwnersByCommunities(communityIds));
            } else if (dataScopeInfo.isOwnerUser()) {
                // 业主用户：显示关联房户数据
                List<Long> householdIds = dataScopeInfo.getHouseholdIds();
                List<Long> communityIds = dataScopeInfo.getCommunityIds();
                
                stats.setTotalUsers(getTotalUsersByHouseholds(householdIds));
                stats.setTotalCommunities(getTotalCommunitiesByIds(communityIds));
                stats.setTotalParkingSpaces(getTotalParkingSpacesByCommunities(communityIds));
                stats.setOnlineDevicesPercent(getDeviceOnlineRateByCommunities(communityIds));
                stats.setTotalBuildings(getTotalBuildingsByCommunities(communityIds));
                stats.setTotalUnits(getTotalUnitsByCommunities(communityIds));
                stats.setTotalHouseholds(getTotalHouseholdsByCommunities(communityIds));
                stats.setTotalOwners(getTotalOwnersByCommunities(communityIds));
            }
            // 普通用户：显示0（已默认设置）
            
        } catch (Exception e) {
            log.error("构建统计数据失败", e);
            // 发生异常时返回默认值
        }

        return stats;
    }

    /**
     * 构建图表数据
     * 
     * @param dataScopeInfo 用户数据权限信息
     * @return 图表数据
     */
    private DashboardChartVO buildChartData(DataScopeInfo dataScopeInfo) {
        // 动态生成最近6个月的月份标签
        List<String> xAxis = generateRecentMonths(6);
        
        List<Integer> userRegistrations = Collections.emptyList();
        List<Integer> propertyFees = Collections.emptyList();
        List<Integer> repairApplications = Collections.emptyList();

        try {
            // 根据用户权限范围获取图表数据
            if (dataScopeInfo.isSuperAdmin()) {
                // 超级管理员：显示所有数据
                userRegistrations = getUserRegistrationTrendForSuperAdmin();
                propertyFees = getPropertyFeeTrendForSuperAdmin();
                repairApplications = getRepairApplicationTrendForSuperAdmin();
            } else if (dataScopeInfo.isPropertyCompanyUser()) {
                // 物业公司用户：显示本公司数据
                List<Long> propertyCompanyIds = dataScopeInfo.getPropertyCompanyIds();
                List<Long> communityIds = dataScopeInfo.getCommunityIds();
                
                log.info("物业公司用户图表数据权限 - 物业公司IDs: {}, 社区IDs: {}", propertyCompanyIds, communityIds);
                
                userRegistrations = getUserRegistrationTrendByCommunities(communityIds);
                propertyFees = getPropertyFeeTrendByCommunities(communityIds);
                repairApplications = getRepairApplicationTrendByCommunities(communityIds);
            } else if (dataScopeInfo.isOwnerUser()) {
                // 业主用户：显示关联社区数据
                List<Long> communityIds = dataScopeInfo.getCommunityIds();
                
                userRegistrations = getUserRegistrationTrendByCommunities(communityIds);
                propertyFees = getPropertyFeeTrendByCommunities(communityIds);
                repairApplications = getRepairApplicationTrendByCommunities(communityIds);
            } else {
                // 普通用户：显示空数据
                userRegistrations = generateEmptyDataList(6);
                propertyFees = generateEmptyDataList(6);
                repairApplications = generateEmptyDataList(6);
            }
            
        } catch (Exception e) {
            log.error("构建图表数据失败", e);
            // 发生异常时返回空数据
            userRegistrations = generateEmptyDataList(6);
            propertyFees = generateEmptyDataList(6);
            repairApplications = generateEmptyDataList(6);
        }

        return DashboardChartVO.builder()
                .xAxis(xAxis)
                .userRegistrations(userRegistrations)
                .propertyFees(propertyFees)
                .repairApplications(repairApplications)
                .build();
    }

    /**
     * 构建公告数据
     */
    private List<DashboardNoticeVO> buildNoticeData() {
        List<DashboardNoticeVO> notices = new ArrayList<>();
        
        notices.add(DashboardNoticeVO.builder()
                .id(1L)
                .title("关于物业费缴费时间调整的通知")
                .createTime("2024-01-15 10:30:00")
                .build());
        
        notices.add(DashboardNoticeVO.builder()
                .id(2L)
                .title("社区停车场管理规定")
                .createTime("2024-01-14 15:20:00")
                .build());
        
        notices.add(DashboardNoticeVO.builder()
                .id(3L)
                .title("春节期间服务安排公告")
                .createTime("2024-01-13 09:45:00")
                .build());

        return notices;
    }
    
    // ==================== 超级管理员统计方法（生产环境优化版本） ====================
    
    /**
     * 获取超级管理员用户总数
     */
    private Long getTotalUsersForSuperAdmin() {
        try {
            return userService.getTotalUserCount();
        } catch (Exception e) {
            log.error("获取超级管理员用户总数失败", e);
            return 0L;
        }
    }
    
    /**
     * 获取超级管理员社区总数
     */
    private Long getTotalCommunitiesForSuperAdmin() {
        try {
            // 暂时返回模拟数据，等待区域服务提供对应接口
            return 24L;
        } catch (Exception e) {
            log.error("获取超级管理员社区总数失败", e);
            return 0L;
        }
    }
    
    /**
     * 获取超级管理员停车位总数
     */
    private Long getTotalParkingSpacesForSuperAdmin() {
        try {
            // 暂时返回模拟数据，等待停车服务提供对应接口
            return 1256L;
        } catch (Exception e) {
            log.error("获取超级管理员停车位总数失败", e);
            return 0L;
        }
    }
    
    /**
     * 获取超级管理员设备在线率
     */
    private Double getDeviceOnlineRateForSuperAdmin() {
        try {
            // 暂时返回模拟数据，等待设备服务提供对应接口
            return 98.5;
        } catch (Exception e) {
            log.error("获取超级管理员设备在线率失败", e);
            return 0.0;
        }
    }
    
    /**
     * 获取超级管理员用户注册趋势
     */
    private List<Integer> getUserRegistrationTrendForSuperAdmin() {
        try {
            return userService.getUserRegistrationTrendForAll(6);
        } catch (Exception e) {
            log.error("获取超级管理员用户注册趋势失败", e);
            return generateEmptyDataList(6);
        }
    }
    
    /**
     * 获取超级管理员物业费趋势
     */
    private List<Integer> getPropertyFeeTrendForSuperAdmin() {
        try {
            // 暂时返回模拟数据，等待物业统计服务提供对应接口
            return Arrays.asList(220, 182, 191, 234, 290, 330);
        } catch (Exception e) {
            log.error("获取超级管理员物业费趋势失败", e);
            return generateEmptyDataList(6);
        }
    }
    
    /**
     * 获取超级管理员维修申请趋势
     */
    private List<Integer> getRepairApplicationTrendForSuperAdmin() {
        try {
            // 暂时返回模拟数据，等待物业统计服务提供对应接口
            return Arrays.asList(150, 232, 201, 154, 190, 330);
        } catch (Exception e) {
            log.error("获取超级管理员维修申请趋势失败", e);
            return generateEmptyDataList(6);
        }
    }
    
    // ==================== 物业公司用户统计方法 ====================
    
    /**
     * 根据物业公司ID列表获取用户总数
     */
    private Long getTotalUsersByPropertyCompanies(List<Long> propertyCompanyIds) {
        try {
            if (propertyCompanyIds == null || propertyCompanyIds.isEmpty()) {
                return 0L;
            }
            return userService.countUsersByPropertyCompanyIds(propertyCompanyIds);
        } catch (Exception e) {
            log.error("根据物业公司ID列表获取用户总数失败，propertyCompanyIds: {}", propertyCompanyIds, e);
            return 0L;
        }
    }
    

    
    /**
     * 根据社区ID列表获取用户注册趋势
     */
    private List<Integer> getUserRegistrationTrendByCommunities(List<Long> communityIds) {
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return generateEmptyDataList(6);
            }
            return userService.getUserRegistrationTrend(communityIds, 6);
        } catch (Exception e) {
            log.error("根据社区ID列表获取用户注册趋势失败，communityIds: {}", communityIds, e);
            return generateEmptyDataList(6);
        }
    }
    

    
    // ==================== 业主用户统计方法 ====================
    
    /**
     * 根据房户ID列表获取用户总数
     */
    private Long getTotalUsersByHouseholds(List<Long> householdIds) {
        try {
            if (householdIds == null || householdIds.isEmpty()) {
                return 0L;
            }
            return userService.countUsersByHouseholdIds(householdIds);
        } catch (Exception e) {
            log.error("根据房户ID列表获取用户总数失败，householdIds: {}", householdIds, e);
            return 0L;
        }
    }
    
    /**
     * 根据社区ID列表获取社区总数
     */
    private Long getTotalCommunitiesByIds(List<Long> communityIds) {
        if (communityIds == null || communityIds.isEmpty()) {
            return 0L;
        }
        
        // 使用safeCall方法进行安全调用
        return safeCall(
            "区域服务",
            "countCommunitiesByIds",
            () -> regionStatisticsFeign.countCommunitiesByIds(communityIds),
            0L
        );
    }
    
    /**
     * 根据社区ID列表获取停车位总数
     */
    private Long getTotalParkingSpacesByCommunities(List<Long> communityIds) {
        if (communityIds == null || communityIds.isEmpty()) {
            return 0L;
        }
        
        // 使用safeCall方法进行安全调用
        return safeCall(
            "停车服务",
            "countParkingSpacesByCommunityIds",
            () -> parkingStatisticsFeign.countParkingSpacesByCommunityIds(communityIds),
            0L
        );
    }
    
    /**
     * 根据社区ID列表获取设备在线率
     */
    private Double getDeviceOnlineRateByCommunities(List<Long> communityIds) {
        if (communityIds == null || communityIds.isEmpty()) {
            return 0.0;
        }
        
        // 使用safeCall方法进行安全调用
        return safeCall(
            "设备服务",
            "getDeviceOnlineRateByCommunityIds",
            () -> deviceStatisticsFeign.getDeviceOnlineRateByCommunityIds(communityIds),
            0.0
        );
    }
    
    /**
     * 根据社区ID列表获取物业费趋势
     */
    private List<Integer> getPropertyFeeTrendByCommunities(List<Long> communityIds) {
        if (communityIds == null || communityIds.isEmpty()) {
            return generateEmptyDataList(6);
        }
        
        // 使用safeCall方法进行安全调用
        return safeCall(
            "物业统计服务",
            "getPropertyFeeTrend",
            () -> propertyStatisticsFeign.getPropertyFeeTrend(communityIds, 6),
            generateEmptyDataList(6)
        );
    }
    
    /**
     * 根据社区ID列表获取维修申请趋势
     */
    private List<Integer> getRepairApplicationTrendByCommunities(List<Long> communityIds) {
        if (communityIds == null || communityIds.isEmpty()) {
            return generateEmptyDataList(6);
        }
        
        // 使用safeCall方法进行安全调用
        return safeCall(
            "物业统计服务",
            "getRepairApplicationTrend",
            () -> propertyStatisticsFeign.getRepairApplicationTrend(communityIds, 6),
            generateEmptyDataList(6)
        );
    }
    
    // ==================== 辅助方法 ====================
    
    /**
     * 生成最近几个月的月份标签
     * 
     * @param months 月份数量
     * @return 月份标签列表，格式如：["2024年8月", "2024年9月", "2024年10月", ...]
     */
    private List<String> generateRecentMonths(int months) {
        List<String> monthLabels = new ArrayList<>();
        try {
            // 获取当前日期
            LocalDate currentDate = LocalDate.now();
            
            // 生成最近几个月的标签
            for (int i = months - 1; i >= 0; i--) {
                LocalDate targetDate = currentDate.minusMonths(i);
                String monthLabel = String.format("%d年%d月", 
                    targetDate.getYear(), 
                    targetDate.getMonthValue());
                monthLabels.add(monthLabel);
            }
            
            log.debug("生成月份标签成功，月份数量：{}，标签：{}", months, monthLabels);
        } catch (Exception e) {
            log.error("生成月份标签失败，月份数量：{}", months, e);
            // 发生异常时返回默认标签
            for (int i = 1; i <= months; i++) {
                monthLabels.add(i + "月");
            }
        }
        
        return monthLabels;
    }
    
    /**
     * 生成指定长度的空数据列表
     * 
     * @param size 列表大小
     * @return 填充0的列表
     */
    private List<Integer> generateEmptyDataList(int size) {
        if (size <= 0) {
            return Collections.emptyList();
        }
        
        List<Integer> emptyList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            emptyList.add(0);
        }
        return emptyList;
    }
    
    @Override
    public void clearDashboardCache(Long userId) {
        try {
            String cacheKey = "dashboard:data:" + userId;
            cacheService.delete(cacheKey);
            log.debug("清除用户仪表盘数据缓存成功，用户ID：{}", userId);
        } catch (Exception e) {
            log.warn("清除用户仪表盘数据缓存失败，用户ID：{}", userId, e);
        }
    }
    
    @Override
    public void clearAllDashboardCache() {
        try {
            // 这里可以使用Redis的pattern删除，或者记录所有用户ID进行批量删除
            // 暂时使用简单的日志记录
            log.info("清除所有用户仪表盘数据缓存");
        } catch (Exception e) {
            log.warn("清除所有用户仪表盘数据缓存失败", e);
        }
    }
    
    // ==================== 新增统计方法 ====================
    
    /**
     * 获取超级管理员的总楼栋数
     * 
     * @return 总楼栋数
     */
    private Long getTotalBuildingsForSuperAdmin() {
        try {
            // 模拟静态数据，实际应该调用区域服务获取
            return 156L;
        } catch (Exception e) {
            log.warn("获取超级管理员总楼栋数失败", e);
            return 0L;
        }
    }
    
    /**
     * 获取超级管理员的单元统计
     * 
     * @return 单元统计
     */
    private Long getTotalUnitsForSuperAdmin() {
        try {
            // 模拟静态数据，实际应该调用区域服务获取
            return 1248L;
        } catch (Exception e) {
            log.warn("获取超级管理员单元统计失败", e);
            return 0L;
        }
    }
    
    /**
     * 获取超级管理员的房户数量
     * 
     * @return 房户数量
     */
    private Long getTotalHouseholdsForSuperAdmin() {
        try {
            // 模拟静态数据，实际应该调用区域服务获取
            return 3456L;
        } catch (Exception e) {
            log.warn("获取超级管理员房户数量失败", e);
            return 0L;
        }
    }
    
    /**
     * 获取超级管理员的业主统计
     * 
     * @return 业主统计
     */
    private Long getTotalOwnersForSuperAdmin() {
        try {
            // 模拟静态数据，实际应该调用用户服务获取
            return 2890L;
        } catch (Exception e) {
            log.warn("获取超级管理员业主统计失败", e);
            return 0L;
        }
    }
    
    /**
     * 根据社区ID列表获取总楼栋数
     * 
     * @param communityIds 社区ID列表
     * @return 总楼栋数
     */
    private Long getTotalBuildingsByCommunities(List<Long> communityIds) {
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return 0L;
            }
            // 模拟静态数据，实际应该调用区域服务获取
            return 156L;
        } catch (Exception e) {
            log.warn("根据社区ID获取总楼栋数失败", e);
            return 0L;
        }
    }
    
    /**
     * 根据社区ID列表获取单元统计
     * 
     * @param communityIds 社区ID列表
     * @return 单元统计
     */
    private Long getTotalUnitsByCommunities(List<Long> communityIds) {
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return 0L;
            }
            // 模拟静态数据，实际应该调用区域服务获取
            return 1248L;
        } catch (Exception e) {
            log.warn("根据社区ID获取单元统计失败", e);
            return 0L;
        }
    }
    
    /**
     * 根据社区ID列表获取房户数量
     * 
     * @param communityIds 社区ID列表
     * @return 房户数量
     */
    private Long getTotalHouseholdsByCommunities(List<Long> communityIds) {
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return 0L;
            }
            // 模拟静态数据，实际应该调用区域服务获取
            return 3456L;
        } catch (Exception e) {
            log.warn("根据社区ID获取房户数量失败", e);
            return 0L;
        }
    }
    
    /**
     * 根据社区ID列表获取业主统计
     * 
     * @param communityIds 社区ID列表
     * @return 业主统计
     */
    private Long getTotalOwnersByCommunities(List<Long> communityIds) {
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return 0L;
            }
            // 模拟静态数据，实际应该调用用户服务获取
            return 2890L;
        } catch (Exception e) {
            log.warn("根据社区ID获取业主统计失败", e);
            return 0L;
        }
    }

}
